package com.kingyea.app.market.timingTask;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kingyea.app.market.apiInterface.service.ApiInterfaceService;
import com.kingyea.app.market.appBaseInfo.bean.AppBaseInfo;
import com.kingyea.app.market.appBaseInfo.bean.AppInfoVo;
import com.kingyea.app.market.appBaseInfo.bean.AppVo;
import com.kingyea.app.market.appBaseInfo.bean.SyncObjVo;
import com.kingyea.app.market.appBaseInfo.service.AppBaseInfoService;
import com.kingyea.app.market.appExtendInfo.bean.AppExtendInfo;
import com.kingyea.app.market.appExtendInfo.service.AppExtendInfoService;
import com.kingyea.app.market.client.MarketServiceClient;
import com.kingyea.app.market.market.bean.Market;
import com.kingyea.app.market.publishMarket.service.PublishMarketService;
import com.kingyea.app.market.syncMission.bean.SyncMission;
import com.kingyea.app.market.syncMission.bean.SyncMission.PushStatus;
import com.kingyea.app.market.syncMission.service.SyncMissionService;
import com.kingyea.app.market.utils.GlobalVar;
import com.kingyea.app.market.utils.StateCode;
import com.kingyea.app.market.utils.page.PageInfo;
import com.kingyea.app.market.versionInfo.bean.VersionInfo;
import com.kingyea.app.market.versionInfo.service.VersionInfoService;
import com.kingyea.mobilepolice.system.Result;
import com.kingyea.mobilepolice.system.exception.BusinessException;
import com.kingyea.mobilepolice.system.job.GlobalJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class syncTimingTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(syncTimingTask.class);

    @Autowired
    private AppBaseInfoService appBaseInfoService;
    @Autowired
    private AppExtendInfoService appExtendInfoService;
    @Autowired
    private PublishMarketService publishMarketService;
    @Autowired
    private ApiInterfaceService apiInterfaceService;
    @Autowired
    private MarketServiceClient marketServiceClient;
    @Autowired
    private VersionInfoService versionInfoService;
    @Autowired
    private SyncMissionService syncMissionService;

    /**
     * 同步任务： 推送
     * 系统角色为：  控制台模式
     *
     * @param
     * @return java.lang.Object
     * @author Mr.Lin
     * @date 2018.03.24 13:40
     */
    @Scheduled(cron = "0 0/2 * * * ?")
    public void pushData() throws Exception {
        // 项目初始化完成后执行，执行条件：内网+控制台
        if (GlobalJob.isIsInit() && (GlobalVar.marketClassify != null && GlobalVar.marketClassify.intValue() == 3) && (GlobalVar.adminMarket != null && GlobalVar.adminMarket.intValue() == 1)) {

            Result<PageInfo<Market>> allMarketResult = marketServiceClient.conditionQuery(Maps.<String, Object>newHashMap());
            if (!allMarketResult.getCode().equals(StateCode.OPERATION_SUCCESS)) {
                LOGGER.error("获取所有市场失败");
                throw new BusinessException(StateCode.SYSTEM_ERROR);
            }
            List<Market> marketListObj = allMarketResult.getData().getList();//JSONObject.parseObject(JSONObject.parseObject(JSONObject.parseObject(marketListJsonStr.toString(), Map.class).get("data").toString(), Map.class).get("list").toString(), new TypeReference<List<Market>>() {});
            //Market adminMarket = marketList.stream().filter(m -> m.getAdminMarket() == 1).findFirst().get();
            //LOGGER.info(JSONObject.parseObject(JSONObject.toJSONString(marketList.get(0)), Market.class));
            List<Market> marketList = Lists.newArrayList();
            for (int i = 0; i < marketListObj.size(); i++) {
                marketList.add(JSONObject.parseObject(JSONObject.toJSONString(marketListObj.get(i)), Market.class));
            }
            if (marketList.stream().filter(m -> m.getAdminMarket() != null && 1 == m.getAdminMarket()).findFirst().isPresent()) {//LOGGER.info("正在推送数据===========");
                //TODO 所有的内网应用url
                List<Market> toBePushMarketList = marketList.stream().filter(m -> m.getMarketClassify() == 3 && null == m.getAdminMarket()).collect(Collectors.toList());
//				LOGGER.info("【需要推送的内网应用】" + JSONObject.toJSONString(toBePushMarketList));
                for (Market toBePushMarket : toBePushMarketList) {

                    try {
                        Map<String, Object> syncMap = new HashMap();
                        syncMap.put("marketCode", toBePushMarket.getMarketCode());
                        List<SyncMission> pushResultList = syncMissionService.getPushResult(syncMap);//获取  等待推送 & 推送失败  记录
                        List<SyncObjVo> baseInfoVoList = Lists.newArrayList();
                        if (pushResultList.size() > 0) {
                            LOGGER.info("正在封装同步数据，请稍等....");
                            for (SyncMission bean : pushResultList) {
                                bean.setStatus(PushStatus.pushing);
                                syncMissionService.update(bean);
                                AppBaseInfo baseInfoObj = appBaseInfoService.getById(bean.getAppCode());//应用信息
                                AppExtendInfo extendObj = appExtendInfoService.getByAppCode(bean.getAppCode());//扩展信息
                                Map<String, Object> map = new HashMap();
                                map.put("version", bean.getVersion());
                                map.put("appCode", bean.getAppCode());
                                map.put("versionType", bean.getVersionType());
                                PageInfo<VersionInfo> versionListObj = (PageInfo<VersionInfo>) versionInfoService.list(map);
                                List<VersionInfo> versionList = versionListObj.getList();
                                syncMissionService.getById(bean.getId());
                                SyncObjVo objVo = new SyncObjVo();
                                if (versionList.size() == 1) {
                                    //封装应用   基础信息，扩展信息，版本信息，推送记录（以更新推送状态）
                                    objVo.setAppBaseInfo(baseInfoObj);
                                    objVo.setAppExtendInfo(extendObj);
                                    objVo.setVersionInfo(versionList.get(0));
                                    objVo.setSyncMission(bean);
                                } else {
                                    System.out.println("请检查应用是否存在或是否版本冲突....");
                                }
                                baseInfoVoList.add(objVo);
                            }
                            LOGGER.info("同步数据完成封装......");
                            LOGGER.info("推送至应用：{}，同步URL：{}", toBePushMarket.getMarketName(), toBePushMarket.getSynchroUrl());
                        } else {
                            LOGGER.info("暂无同步数据需要封装....");
                        }
                        if (baseInfoVoList != null && baseInfoVoList.size() > 0) {// 有东西推送再执行推送逻辑
                            //TODO 管理端通知内网应用
                            HttpHeaders headers = new HttpHeaders();
                            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                            HttpEntity<List<SyncObjVo>> requestEntity = new HttpEntity<>(baseInfoVoList, headers);
                            AppVo appVo = new AppVo();
                            try {
                                Result<AppVo> appVoreSult = new RestTemplate().postForObject(toBePushMarket.getSynchroUrl() + "/appBaseInfo/doSync", requestEntity, new Result<AppVo>().getClass());
                                Map<String, Object> map2 = (Map<String, Object>) JSONObject.parse(JSONObject.toJSONString(appVoreSult.getData()));
                                List<AppInfoVo> successList = JSONObject.parseObject(map2.get("successList").toString(), new TypeReference<List<AppInfoVo>>() {
                                });
                                List<AppInfoVo> failList = JSONObject.parseObject(map2.get("failList").toString(), new TypeReference<List<AppInfoVo>>() {
                                });

                                appVo.setSuccessList(successList);
                                appVo.setFailList(failList);
//                                LOGGER.info(JSONObject.toJSONString(appVoreSult.getData()));
                                //ResponseEntity<AppVo> entity = new RestTemplate().exchange(toBePushMarket.getSynchroUrl() + "/appBaseInfo/doSync", HttpMethod.POST, requestEntity, AppVo.class);
                                if (appVo == null) {
                                    LOGGER.warn("推送后得到的反馈数据为空：" + JSON.toJSONString(appVo));
                                } else {
                                    updateNotify(appVo);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                LOGGER.error("推送失败{}", e.getLocalizedMessage());
                            }
                            LOGGER.info("【已推送内网应用结果】" + JSONObject.toJSONString(appVo));
                        } else {
                            LOGGER.info("暂无需要推送的数据");
                        }
                    } catch (Exception e) {
                        LOGGER.error("【推送内网应用失败】" + JSONObject.toJSONString(toBePushMarket), e);
                    }
                }
            }
        }
    }

    private boolean updateNotify(AppVo appVo) throws Exception {
        if (appVo != null && appVo.getSuccessList() != null && appVo.getFailList() != null) {
            List<AppInfoVo> successList = appVo.getSuccessList();
            for (AppInfoVo app : successList) {
                SyncMission syncMission = new SyncMission();
                syncMission.setId(app.getSyncMissionId());
            /*syncMission.setAppCode(app.getAppCode());
            syncMission.setVersion(app.getVersionCode());
            syncMission.setMarketCode(app.getMarketCode());*/
                syncMission.setStatus(PushStatus.pushSuccess);
                syncMissionService.update(syncMission);
                LOGGER.info("【推送成功！！】");
            }

            List<AppInfoVo> failList = appVo.getFailList();
            for (AppInfoVo app : failList) {
                SyncMission syncMission = new SyncMission();
                syncMission.setId(app.getSyncMissionId());
           /* syncMission.setAppCode(app.getAppCode());
            syncMission.setVersion(app.getVersionCode());
            syncMission.setMarketCode(app.getMarketCode());*/
                syncMission.setStatus(PushStatus.pushFailure);
                syncMissionService.update(syncMission);
                LOGGER.info("【推送失败！！】");
            }
            return true;
        }
        return true;
    }


    /**
     * 同步任务： 拿数据
     * 系统角色为：  外网应用市场模式
     *
     * @param
     * @return void
     * @author Mr.Lin
     * @date 2018.03.24 13:42
     */
    @Scheduled(cron = "0 0/2 * * * ?")
    public void pullData() {
        // 项目初始化完成后执行，执行条件：外网应用市场
        if (GlobalJob.isIsInit() && GlobalVar.marketClassify.intValue() == 2) {
            LOGGER.info("试图拉取数据===========");
            try {
                Result<PageInfo<Market>> marketResult = marketServiceClient.conditionQuery(Maps.<String, Object>newHashMap());
                if (!marketResult.getCode().equals(StateCode.OPERATION_SUCCESS)) {
                    LOGGER.info(" 外网应用市场模式-拿数据-   失败  :" + JSON.toJSONString(marketResult));
                    return;
                }
                List<Market> marketList = marketResult.getData().getList();//JSONObject.parseObject(JSONObject.parseObject(JSONObject.parseObject(marketListJsonStr.toString(), Map.class).get("data").toString(), Map.class).get("list").toString(), new TypeReference<List<Market>>() {});
                Market market = JSONObject.parseObject(JSONObject.toJSONString(marketList.get(0)), Market.class);
                //TODO 外部应用条件
                if (market.getAdminMarket() == null && market.getMarketClassify() == 2) {
                    LOGGER.info("正在拉取数据=======");

                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    Market marketParam = new Market();
                    marketParam.setMarketCode(market.getMarketCode());
                    HttpEntity<Market> requestEntity = new HttpEntity<>(marketParam, headers);
                    // TODO 这里要使用管理端的url
                    Result appInfoVoResult = new RestTemplate().postForObject(market.getSynchroUrl() + "/appBaseInfo/searchSyncData", requestEntity, Result.class);
                    if (!appInfoVoResult.getCode().equals(StateCode.OPERATION_SUCCESS)) {
                        LOGGER.error("【拉取失败】");
                        throw new BusinessException(StateCode.SYNC_GET_DATE_ERROR);
                    }
                    //System.out.println(str);
                    List<SyncObjVo> appInfoVoList = JSONObject.parseArray(JSON.toJSONString(appInfoVoResult.getData()), SyncObjVo.class);
                    LOGGER.info("【成功拉取推送至本地市场数据，准备推送...】");
                    if (appInfoVoList.size() > 0) {
                        //TODO 记录成功的数据的唯一标识，最后发送给监控端
                        List<AppInfoVo> successAppInfoVoList = Lists.<AppInfoVo>newArrayList();
                        //TODO 记录失败的数据的唯一标识，最后发送给监控端
                        List<AppInfoVo> failAppInfoVoList = Lists.<AppInfoVo>newArrayList();
                        appInfoVoList.forEach(appInfoVo -> {
                            try {
                                System.out.println(appInfoVo.toString());
                                appBaseInfoService.save(appInfoVo);
//								Map<String, Object> versionMap = Maps.newHashMap();
//								versionMap.put("appCode", appInfoVo.getAppCode());
//								versionMap.put("versionType", appInfoVo.getVersionInfo().getVersionType());
//								versionMap.put("versionCode", appInfoVo.getVersionInfo().getVersion());
//								PageInfo versionPageInfo = (PageInfo)versionInfoService.list(versionMap);
//								if(versionPageInfo.getTotal() == 0) {//已存在版本数据
//									appBaseInfoService.save(appInfoVo);//保存应用基本信息
//	
//								}
                                AppInfoVo vo = new AppInfoVo();
                                vo.setSyncMissionId(appInfoVo.getSyncMission().getId());
								/*vo.setAppCode(appInfoVo.getAppCode());
								vo.setMarketCode(appInfoVo.getMarketCode());
								vo.setVersionCode(appInfoVo.getVersionCode());*/
                                successAppInfoVoList.add(vo);
                            } catch (Exception e) {
                                LOGGER.error("【推送失败，应用编码：{}，应用名称】", appInfoVo.getAppBaseInfo().getAppCode(), appInfoVo.getAppBaseInfo().getAppName(), e);

                                AppInfoVo vo = new AppInfoVo();
                                vo.setSyncMissionId(appInfoVo.getSyncMission().getId());
								/*vo.setAppCode(appInfoVo.getAppCode());
								vo.setMarketCode(appInfoVo.getMarketCode());
								vo.setVersionCode(appInfoVo.getVersionCode());*/
                                failAppInfoVoList.add(vo);

                            }
                        });

                        AppVo appVo = new AppVo();
                        appVo.setFailList(failAppInfoVoList);
                        appVo.setSuccessList(successAppInfoVoList);

                        //TODO 通知监控端
                        HttpHeaders notifyHeaders = new HttpHeaders();
                        notifyHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
                        HttpEntity<AppVo> notifyRequestEntity = new HttpEntity<>(appVo, headers);
                        // TODO 这里要使用管理端的url
                        String str = new RestTemplate().postForObject(market.getSynchroUrl() + "/appBaseInfo/notify", notifyRequestEntity, String.class);
                    }
                    LOGGER.info("【暂无需要推送至本地市场数据】");

                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

	/*public static void main(String[] args) throws Exception{
		String jsonStr = "{\"code\":\"S100101\",\"msg\":\"操作成功\",\"data\":{\"pageNum\":1,\"pageSize\":10,\"total\":3,\"list\":[{\"marketCode\":\"19\",\"marketName\":\"222222\",\"adminArea\":\"[{\\\"code\\\":\\\"140000\\\",\\\"name\\\":\\\"山西省\\\"},{\\\"code\\\":\\\"140300\\\",\\\"name\\\":\\\"阳泉市\\\"},{\\\"code\\\":\\\"140303\\\",\\\"name\\\":\\\"矿区\\\"},{\\\"code\\\":\\\"140303004000\\\",\\\"name\\\":\\\"赛鱼街道\\\"}]\",\"marketType\":\"测试环境\",\"companyCode\":\"22\",\"synchroUrl\":\"222\",\"isSynchro\":1,\"createDate\":1521857611000,\"updateDate\":null,\"isEnable\":-1,\"clazz\":null,\"marketClassify\":3,\"localMarket\":null,\"adminMarket\":null},{\"marketCode\":\"18\",\"marketName\":\"1\",\"adminArea\":\"[{\\\"code\\\":\\\"140000\\\",\\\"name\\\":\\\"山西省\\\"},{\\\"code\\\":\\\"140100\\\",\\\"name\\\":\\\"太原市\\\"},{\\\"code\\\":\\\"140105\\\",\\\"name\\\":\\\"小店区\\\"},{\\\"code\\\":\\\"140105001000\\\",\\\"name\\\":\\\"坞城街道\\\"}]\",\"marketType\":\"测试环境\",\"companyCode\":\"1\",\"synchroUrl\":\"1\",\"isSynchro\":1,\"createDate\":1521793385000,\"updateDate\":null,\"isEnable\":-1,\"clazz\":null,\"marketClassify\":2,\"localMarket\":1,\"adminMarket\":null},{\"marketCode\":\"16\",\"marketName\":\"市场1\",\"adminArea\":\"[{\\\"code\\\":\\\"140000\\\",\\\"name\\\":\\\"山西省\\\"},{\\\"code\\\":\\\"140400\\\",\\\"name\\\":\\\"长治市\\\"},{\\\"code\\\":\\\"140423\\\",\\\"name\\\":\\\"襄垣县\\\"},{\\\"code\\\":\\\"140423102000\\\",\\\"name\\\":\\\"侯堡镇\\\"}]\",\"marketType\":\"测试环境\",\"companyCode\":\"1\",\"synchroUrl\":\"1\",\"isSynchro\":1,\"createDate\":1521788229000,\"updateDate\":null,\"isEnable\":-1,\"clazz\":null,\"marketClassify\":3,\"localMarket\":1,\"adminMarket\":1}]}}";
		System.out.println(jsonStr);
		Map<String, Object> jsonMap = JSONObject.parseObject(jsonStr, Map.class);

		System.out.println("==============");
		System.out.println(jsonMap.get("data").toString());

		Map<String, Object> pageInfoMap = JSONObject.parseObject(jsonMap.get("data").toString(), Map.class);
		System.out.println(pageInfoMap.get("list"));
		System.out.println(pageInfoMap.get("total"));

		List<Market> marketList = JSONObject.parseObject(JSONObject.parseObject(JSONObject.parseObject(jsonStr, Map.class).get("data").toString(), Map.class).get("list").toString(), new TypeReference<List<Market>>(){});
		System.out.println("---------------------------------");
		System.out.println(marketList.size());
		System.out.println(marketList.get(0).getMarketCode());


	}*/
//    public static void main(String[] args) {
//        String str = "{\"code\":\"S100101\",\"msg\":\"操作成功\",\"data\":{\"successList\":[{\"appCode\":\"test\",\"appName\":null,\"appMarket\":null,\"appType\":null,\"appSource\":null,\"createDate\":null,\"updateDate\":null,\"logoImage\":null,\"developer\":null,\"recommend\":null,\"sort\":null,\"remark\":null,\"extendMap\":null,\"apiMap\":null,\"versionMap\":null,\"market\":null,\"applicationType\":null,\"publishFlag\":null,\"marketCode\":\"99\",\"versionCode\":\"0.0.1\",\"syncMissions\":null}],\"failList\":[]}}";
//        System.out.println(str);
//        Map<String, Object> map = (Map<String, Object>)JSONObject.parse(str);
//        Map<String, Object> map2 = (Map<String, Object>)JSONObject.parse(JSONObject.toJSONString(map.get("data")));
//        List<AppInfoVo> successList = JSONObject.parseObject(map2.get("successList").toString(), new TypeReference<List<AppInfoVo>>(){});
//        List<AppInfoVo> failList = JSONObject.parseObject(map2.get("failList").toString(), new TypeReference<List<AppInfoVo>>(){});
//        System.out.println(successList);
//        System.out.println(failList);
//
//    }
}
